package com.marver.common.jackson;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.marver.common.enumeration.StringLabeledEnum;

/**
 * jackson 序列化 NUll处理
 * @author kaede
 *
 */
public class MyBeanSerializerModifier extends BeanSerializerModifier {
    private JsonSerializer<Object> arrayJsonSerializer = new ArrayJsonSerializer();
    private JsonSerializer<Object> numberJsonSerializer = new NumberJsonSerializer();
    private JsonSerializer<Object> otherJsonSerializer = new OtherJsonSerializer();
    private JsonSerializer<Object> stringLabeledEnumJsonSerializer = new StringLabeledEnumJsonSerializer();

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc,
            List<BeanPropertyWriter> beanProperties) {
    	  
    	
    	//判断是否有JsonInclude的注解，如果有就不处理Null
    	Class<?> bean=beanDesc.getBeanClass();
    	
    	//获取类上所有注解
    	Annotation[] allAnnotations = bean.getAnnotations();
    	for(Annotation an : allAnnotations){ 
    		if(an.annotationType().equals(JsonInclude.class)){//找到JsonInclude的注解
    			JsonInclude j=(JsonInclude)an;
    			if(j.value().name().equals(JsonInclude.Include.NON_EMPTY.name())||
    					j.value().name().equals(JsonInclude.Include.NON_NULL.name())){
    				return beanProperties;
    			}
    		}
    	}
    	//获取属性上所有注解
    	List<Field> list=Arrays.asList(bean.getDeclaredFields());
    	List<String> hasAnnotation=new ArrayList<String>();
    	if(list!=null&&list.size()>0){
	        for(int i=0;i<list.size();i++){
		        if(list.get(i).isAnnotationPresent(JsonInclude.class)){//是否使用JsonInclude注解
		        	for (Annotation anno : list.get(i).getDeclaredAnnotations()) {//获得所有的注解
		                if(anno.annotationType().equals(JsonInclude.class) ){//找到JsonInclude的注解
		        			JsonInclude j=(JsonInclude)anno;
		        			if(j.value().name().equals(JsonInclude.Include.NON_EMPTY.name())||
		        					j.value().name().equals(JsonInclude.Include.NON_NULL.name())){
		        				hasAnnotation.add(list.get(i).getName());
		        			}
		                }
		        	}
		        }
	        }
    	}
	    // 循环所有的beanPropertyWriter
	    for (int i = 0; i < beanProperties.size(); i++) {
	    	BeanPropertyWriter writer = beanProperties.get(i);
	    	Class<?> clazz = writer.getType().getRawClass();
	    	if(clazz.equals(StringLabeledEnum.class)){
	    		//数据字典
	    		writer.assignSerializer(stringLabeledEnumJsonSerializer);
	    	}
	    	if(!hasAnnotation.contains(writer.getName())){
		        if (isArrayType(clazz)) {
		        	// 判断字段的类型，如果是array，list，set则注册MyNullArrayJsonSerializer
		             //给writer注册一个自己的nullSerializer
		            writer.assignNullSerializer(this.defaultNullArrayJsonSerializer());
		        }
		        else if (isNumberType(clazz)) {
		        	// 判断字段的类型，如果是数值类型 则 注册MyNullNumberJsonSerializer
		             //给writer注册一个自己的nullSerializer
		            writer.assignNullSerializer(this.defaultNullNumberJsonSerializer());	        	
		        }
		        else{
		             //给writer注册一个自己的nullSerializer
		            writer.assignNullSerializer(this.defaultNullOtherJsonSerializer());		        	
		        }
	    	}
	    }
	    return beanProperties;
    }
    
    // 判断是什么类型
    protected boolean isArrayType(Class<?> clazz) {
        return clazz.isArray() || clazz.equals(List.class) || clazz.equals(Set.class);
    }
    // 判断是否数值类型
    protected boolean isNumberType(Class<?> clazz) {
        return clazz.equals(Integer.class) || clazz.equals(Double.class)||
        		clazz.equals(Short.class) || clazz.equals(Long.class)||
        		clazz.equals(Float.class) || clazz.equals(BigDecimal.class);
    }

    protected JsonSerializer<Object> defaultNullArrayJsonSerializer() {
        return arrayJsonSerializer;
    }
    protected JsonSerializer<Object> defaultNullOtherJsonSerializer() {
        return otherJsonSerializer;
    }
    protected JsonSerializer<Object> defaultNullNumberJsonSerializer() {
        return numberJsonSerializer;
    }
    
    /**
     * 定义List Array Set 的Null输出[]
     * @author kaede
     *
     */
    protected class ArrayJsonSerializer extends JsonSerializer<Object> {
    	
    	@Override
    	public void serialize(Object value, JsonGenerator gen,
    			SerializerProvider serializers) throws IOException,
    			JsonProcessingException {
            if (value == null) {
            	gen.writeStartArray();
            	gen.writeEndArray();
            } else {
            	gen.writeObject(value);
            }
    	}
    }
    
    /**
     * 定义String的 Null输出""
     * @author kaede
     *
     */
    protected class OtherJsonSerializer extends JsonSerializer<Object> {
    	
    	@Override
    	public void serialize(Object value, JsonGenerator gen,
    			SerializerProvider serializers) throws IOException,
    			JsonProcessingException {
            if (value == null) {
            	gen.writeString("");
            } else {
            	gen.writeObject(value);
            }
    	}
    }
    
    /**
     * 定义Number型 的 Null输出0
     * @author kaede
     *
     */
    protected class NumberJsonSerializer extends JsonSerializer<Object> {
    	
    	@Override
    	public void serialize(Object value, JsonGenerator gen,
    			SerializerProvider serializers) throws IOException,
    			JsonProcessingException {
            if (value == null) {
            	gen.writeObject(0);
            } else {
            	gen.writeObject(value);
            }
    	}
    }

    /**
     * 定义StringLabeledEnum型 的输出Label
     * @author kaede
     *
     */
    protected class StringLabeledEnumJsonSerializer extends JsonSerializer<Object> {
    	
    	@Override
    	public void serialize(Object value, JsonGenerator gen,
    			SerializerProvider serializers) throws IOException,
    			JsonProcessingException {
            if (value == null) {
            	gen.writeString("");
            } else {
            	StringLabeledEnum vl=(StringLabeledEnum)value;
            	gen.writeObject(vl.getLabel());
            }
    	}
    }
    
}
